#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>

#include <sys/mman.h>

#define AXGPIO_PHYADDR   0x41200000   // 0 TB, 1 KZ, 2 ZJ 

#define UART485_PHYADDR2 0x42c20000   // TB
#define UART485_PHYADDR3 0x42c30000   // KZ
#define UART485_PHYADDR4 0x42c40000   // ZJ

unsigned int * addr_axigpio;

void axi_gpio_init() {
    int fd = open("/dev/mem", O_RDWR | O_NOCTTY);
    if(fd < 0) {
        printf("error open /dev/mem; fd: %d \n", fd);
        return;
    }
    addr_axigpio = (unsigned int *)mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, AXGPIO_PHYADDR);
    printf("addr_axigpio %p \n", addr_axigpio);

    if((void *)0 != addr_axigpio) {
        printf("error to mmap AXGPIO_PHYADDR: %0x", AXGPIO_PHYADDR);
        exit(-1);
    }
}

// 485 需要加这个AXI_IO控制, 如果是422就不需要
void setAxiGpioVal(int val, int addr) {
    addr_axigpio[addr] = val;
    printf("set axi gpio val:%d\n", val);
    usleep(1000*1000);
}

int init_serial_device(int baud, int fd)
{
    int ret;
    struct termios options;

    ret = tcgetattr(fd, &options);
    if (-1 == ret)
        return -1;


    options.c_cflag &= ~CSIZE;    //屏蔽其他标志
    options.c_cflag |= CS8;        //将数据位修改为8bit
    options.c_cflag |= (PARODD|PARENB);
    options.c_cflag &= ~CSTOPB; // 设置一位停止位;


    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    cfsetispeed(&options, baud);
    cfsetospeed(&options, baud);
    options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
    options.c_cc[VTIME] = 10; // 超时时间 单位 100ms
	options.c_cc[VMIN] = 0;
    ret = tcsetattr(fd, TCSANOW, &options);
    if (-1 == ret)
        return -1;
    return fd;
}

int main(int argc, char const *argv[])
{
    axi_gpio_init(); //485

    printf("a.out %c [9c a0 00 5f ff] \n", argv[1]);

    unsigned char send[5] = { 0x9c, 0xa0, 0x00, 0x5f, 0xff };
    unsigned char recv[5] = { 0x00 };
    long long total_time;
    unsigned char ParaVal = 0;

    int slen1 = atoi(argv[1]);
    printf("slen=> %d \n", slen1);

    int i = 0; 
    printf("uart=>");
    for(i = 0; i < slen1; i++) {
        printf("%02x ", send[i]);
    }
    printf("\n");

    int fd = open("/dev/ttyUL0", O_RDWR | O_NOCTTY);     /* 读写权限，非阻塞 */
    // int fd = open("/dev/ttyUL0", O_RDWR);     /* 读写权限，非阻塞 */
    init_serial_device(B19200, fd);
    printf("fd => %d \n", fd);

    setAxiGpioVal(1, 0);
    int slen = write(fd, send, slen1);
    printf("slen => %d \n", slen);

    int rlen = 0;
    int times = 0;
    setAxiGpioVal(0, 0);
    while(1) {
        rlen = read(fd, recv, 4);

        if(rlen != 0) {
            printf("rlen => %d %02x\n", rlen, recv[0]);
            times = 0;
        } else {
            times++;
        }
        if(rlen < 0) {
            printf("rlen: %d \n", rlen);
        }

        if(times == 4) {                //4s 延迟
            printf("times out \n");
            return 0;
        }

    }

    printf("recv=>");
    for(i = 0; i < slen1; i++) {
        printf("%02x ", recv[i]);
    }
    printf("\n");

    return 0;
}


